package com.leyou.order.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.leyou.common.auth.pojo.UserHolder;
import com.leyou.common.constants.LyConstants;
import com.leyou.common.constants.MQConstants;
import com.leyou.common.exception.pojo.ExceptionEnum;
import com.leyou.common.exception.pojo.LyException;
import com.leyou.common.pojo.PageResult;
import com.leyou.common.utils.BeanHelper;
import com.leyou.item.client.ItemClient;
import com.leyou.item.entity.Sku;
import com.leyou.order.dto.CartDTO;
import com.leyou.order.dto.OrderDTO;
import com.leyou.order.dto.OrderStatusEnum;
import com.leyou.order.dto.OrderVO;
import com.leyou.order.entity.Order;
import com.leyou.order.entity.OrderDetail;
import com.leyou.order.entity.OrderLogistics;
import com.leyou.order.mapper.OrderDetailMapper;
import com.leyou.order.mapper.OrderLogisticsMapper;
import com.leyou.order.mapper.OrderMapper;
import com.leyou.order.utils.PayHelper;
import com.leyou.user.client.UserClient;
import com.leyou.user.dto.AddressDTO;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@Transactional
public class OrderService extends ServiceImpl<OrderDetailMapper, OrderDetail> {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private OrderDetailMapper orderDetailMapper;

    @Autowired
    private OrderLogisticsMapper orderLogisticsMapper;

    @Autowired
    private UserClient userClient;

    @Autowired
    private ItemClient itemClient;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private PayHelper payHelper;
    
    @Autowired
    private AmqpTemplate amqpTemplate;

    @GlobalTransactional
    public Long saveOrder(OrderDTO orderDTO) {
        try {
            //保存订单
            //创建一个订单对象
            Order order = new Order();
            order.setStatus(OrderStatusEnum.INIT.value());
            order.setPaymentType(orderDTO.getPaymentType());
            order.setInvoiceType(0);
            order.setSourceType(2);
            order.setUserId(UserHolder.getUserId());
            order.setPostFee(0L);
            //计算总金额  每个sku的价格[需要查询]*购买的数量[页面提交的] 最终相加即可。
            //获取提交的购买的购物车的信息
            List<CartDTO> carts = orderDTO.getCarts();
            //将列表类型的集合转成map结构
            Map<Long, Integer> cartMap = carts.stream().collect(Collectors.toMap(CartDTO::getSkuId, CartDTO::getNum));
            //从购物车信息中获取到所有sku的id的集合
            List<Long> skuIds = carts.stream().map(CartDTO::getSkuId).collect(Collectors.toList());
            //通过sku的id的集合获取的对象的集合
            List<Sku> skus = itemClient.findSkusByIds(skuIds);
            //以流的方式获取到skus集合中每个sku的的价格并直接与购买数量相乘
            long totalFee = skus.stream().mapToLong(sku -> sku.getPrice() * cartMap.get(sku.getId())).sum();
            order.setTotalFee(totalFee);//总金额
            order.setActualFee(1L);//实付款金额
            //订单入库
            orderMapper.insert(order);

            //获取订单号
            Long orderId = order.getOrderId();

            //保存订单详情
            List<OrderDetail> orderDetails = new ArrayList<>();
            //遍历sku的集合
            skus.forEach(sku -> {
                OrderDetail orderDetail = new OrderDetail();
                orderDetail.setOrderId(orderId);
                orderDetail.setSkuId(sku.getId());
                orderDetail.setTitle(sku.getTitle());
                orderDetail.setPrice(sku.getPrice());
                orderDetail.setOwnSpec(sku.getOwnSpec());
                orderDetail.setImage(StringUtils.substringBefore(sku.getImages(), ","));
                orderDetail.setNum(cartMap.get(sku.getId()));
                orderDetails.add(orderDetail);
            });
            //订单详情入库
            saveBatch(orderDetails);

            //保存订单物流信息
            //查询出物流信息
            AddressDTO addressDTO = userClient.queryAddressById(UserHolder.getUserId(), orderDTO.getAddressId());
            //将物流的dto对象转成entity对象
            OrderLogistics orderLogistics = BeanHelper.copyProperties(addressDTO, OrderLogistics.class);
            //给订单号赋值
            orderLogistics.setOrderId(orderId);
            //地址入库
            orderLogisticsMapper.insert(orderLogistics);

            //减库存
            itemClient.minusStock(cartMap);

            //下单后删除购物车的商品
            HashMap<Long, List<Long>> map = new HashMap<>();
            map.put(UserHolder.getUserId(), skuIds);
            amqpTemplate.convertAndSend(MQConstants.Exchange.ITEM_EXCHANGE_NAME,
                    MQConstants.RoutingKey.CART_DELETE_KEY, map);
            //int i = 1/0;
            return orderId;
        }catch (Exception e){
            e.printStackTrace();
            throw new LyException(ExceptionEnum.INSERT_OPERATION_FAIL);
        }

    }

    public OrderVO findOrderVOById(Long id) {
        try {
            //查询订单对象
            Order order = orderMapper.selectById(id);
            //将Order对象转成OrderVO对象
            OrderVO orderVO = BeanHelper.copyProperties(order, OrderVO.class);
            //根据订单号查询订单详情
            OrderDetail entity = new OrderDetail();
            entity.setOrderId(order.getOrderId());
            QueryWrapper<OrderDetail> wrapper = Wrappers.query(entity);
            List<OrderDetail> orderDetails = orderDetailMapper.selectList(wrapper);
            //将订单详情赋值给订单对象
            orderVO.setDetailList(orderDetails);
            //根据订单号查询物流信息
            OrderLogistics orderLogistics = orderLogisticsMapper.selectById(order.getOrderId());
            //将物流信息赋值给订单对象
            orderVO.setLogistics(orderLogistics);
            return orderVO;
        }catch (Exception e){
            throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
        }
    }

    public String getPayUrl(Long id) {
        //获取当前订单在redis中存放的支付链接的key
        String key = LyConstants.PAY_URL_PRE+id;
        //判断redis中是否有url地址
        if(redisTemplate.hasKey(key)){
            return redisTemplate.opsForValue().get(key);
        }
        //根据订单id查询订单对象
        Order order = orderMapper.selectById(id);
        if(order==null){
            throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
        }
        //判断订单状态
        if(order.getStatus()!=1){
            throw new LyException(ExceptionEnum.INVALID_ORDER_STATUS);
        }
        //获取支付链接
        String codeUrl = payHelper.getCodeUrl(id, order.getActualFee());
        //将支付链接存入redis
        redisTemplate.opsForValue().set(key, codeUrl, 2, TimeUnit.HOURS);
        return codeUrl;
    }

    public Integer queryOrderStatus(Long id) {
        Order order = orderMapper.selectById(id);
        if(order==null){
            throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
        }
        return order.getStatus();
    }

    public Map<String, String> wxNotify(Map<String, String> resp) {
        log.info("【微信支付回调】开始！");
        //校验返回结果是否合法
        payHelper.checkResp(resp);
        //获取微信回调中的订单号
        String outTradeNo = resp.get("out_trade_no");
        //将订单号转成Long类型
        Long orderId = Long.valueOf(outTradeNo);
        //获取微信回调中的支付金额
        String totalFee = resp.get("total_fee");
        //根据订单号查询订单
        Order order = orderMapper.selectById(orderId);
        if(order==null){
            log.error("【微信支付回调】订单不存在！");
            throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
        }
        //比对金额
        if(!Long.valueOf(totalFee).equals(order.getActualFee())){
            log.error("【微信支付回调】付款金额不正确！");
            throw new LyException(501, "付款金额不正确");
        }
        //修改订单状态
        Order entity = new Order();
        entity.setOrderId(orderId);
        entity.setStatus(OrderStatusEnum.PAY_UP.value());
        int i = orderMapper.updateById(entity);
        if(i!=1){
            log.error("【微信支付回调】修改订单状态失败！");
        }
        Map<String, String> result = new HashMap<>();
        result.put("return_code", "SUCCESS");
        result.put("return_msg", "OK");
        log.info("【微信支付回调】成功结束！");
        return result;
    }

    public Map<Long, Integer> clean() {
        Map<Long, Integer> map = null;
        List<Long> ids = orderMapper.findOrderIds();
        orderMapper.changeStatus(ids);
        ids.forEach(id -> {
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setOrderId(id);
            QueryWrapper<OrderDetail> queryWrapper = Wrappers.query(orderDetail);
            List<OrderDetail> orderDetailList = orderDetailMapper.selectList(queryWrapper);
            new HashMap<>();
            orderDetailList.forEach(orderDetail1 -> {
                map.put(orderDetail1.getSkuId(), orderDetail1.getNum());
            });
        });
        return map;
    }

    /**
     * 订单分页显示
     *
     * @param page
     * @param rows
     * @return
     */
    public PageResult<OrderVO> orderPageList(Integer status, Integer page, Integer rows) {
        //封装分页信息
        IPage<Order> iPage = new Page(page, rows);
        //封装查询对象
        QueryWrapper<Order> wrapper = Wrappers.query();
        if (status != null) {
            switch (status) {
                case 1:
                    wrapper.eq("status", 1);
                    break;
                case 2:
                    wrapper.eq("status", 2);
                    break;
                case 3:
                    wrapper.eq("status", 3);
                    break;
                case 4:
                    wrapper.eq("status", 4);
                    break;
                default:
                    return null;
            }
        }

        iPage = orderMapper.selectPage(iPage, wrapper);
        //一页的数据
        List<Order> orders = iPage.getRecords();
        //将order集合转为orderVO
        List<OrderVO> orderVOS = BeanHelper.copyWithCollection(orders, OrderVO.class);

        //遍历orderVO集合赋值
        orderVOS.forEach(orderVO -> {
            //获取订单号
            Long orderId = orderVO.getOrderId();
            //根据订单号获取物流路线和商品详情
            // 物流
            OrderLogistics orderLogistics = orderLogisticsMapper.selectById(orderId);
            orderVO.setLogistics(orderLogistics);
            // 商品详情
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setOrderId(orderId);
            QueryWrapper<OrderDetail> query = Wrappers.query(orderDetail);
            List<OrderDetail> orderDetails = orderDetailMapper.selectList(query);
            orderVO.setDetailList(orderDetails);
        });

        PageResult<OrderVO> pageResult = new PageResult<OrderVO>(
                iPage.getPages(),
                iPage.getTotal(),
                orderVOS
        );
        return pageResult;
    }
}